﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace Admin.CYT369.Com.Utility
{
    public class OssClientService
    {
        private static readonly OssClientService m_Instance = new OssClientService();
        private static object m_lock = new object();
        private static object m_lock_file = new object();
        private OssClientService() { }

        public static OssClientService Instance
        {
            get
            {
                return m_Instance;
            }
        }

        public bool SaveFile(EndpointParameter endpoint, string key, string file, bool defaultValue = false)
        {
            if (!string.IsNullOrEmpty(key))
            {
                if (System.IO.File.Exists(file))
                {
                    lock (m_lock_file)
                    {
                        return this.SaveFile(endpoint, key, System.IO.File.ReadAllBytes(file), defaultValue);
                    }
                }
            }

            return defaultValue;
        }

        public bool SaveFile(EndpointParameter endpoint, string key, System.IO.Stream file, bool defaultValue = false)
        {
            if (!string.IsNullOrEmpty(key) && file != null)
            {
                lock (m_lock)
                {
                    var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);
                    var result = ossClient.PutObject(endpoint.Bucket, key, file);

                    if (result.HttpStatusCode == System.Net.HttpStatusCode.OK)
                    {
                        return true;
                    }
#if DEBUG
                    else
                    {
                        Console.WriteLine("\t返回状态码 {0}", result.HttpStatusCode);
                    }
#endif
                }
            }

            return defaultValue;
        }

        public bool SaveFile(EndpointParameter endpoint, string key, byte[] file, bool defaultValue = false)
        {
            if (!string.IsNullOrEmpty(key) && file != null)
            {
                return this.SaveFile(endpoint, key, new System.IO.MemoryStream(file));
            }

            return defaultValue;
        }

        public bool RemoveFile(EndpointParameter endpoint, string key)
        {
            if (!string.IsNullOrEmpty(key))
            {
                lock (m_lock)
                {
                    try
                    {
                        var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);
                        ossClient.DeleteObject(endpoint.Bucket, key);
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                }
            }

            return true;
        }


        public bool UpdateFile(EndpointParameter endpoint, string key, System.IO.Stream file, bool defaultValue = false)
        {
            if (!string.IsNullOrEmpty(key) && file != null)
            {
                string newKey = string.Format("temp/{0}", Guid.NewGuid());
                if (this.SaveFile(endpoint, newKey, file))
                {
                    string tempKey = string.Format("temp/remove_key/{0}", key);
                    lock (m_lock)
                    {
                        try
                        {
                            var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);
                            var result = ossClient.CopyObject(new Aliyun.OSS.CopyObjectRequest(endpoint.Bucket, key, endpoint.Bucket, tempKey));
                            if (result != null && result.HttpStatusCode == System.Net.HttpStatusCode.OK)
                            {
                                ossClient.DeleteObject(endpoint.Bucket, key);

                                try
                                {
                                    result = ossClient.CopyObject(new Aliyun.OSS.CopyObjectRequest(endpoint.Bucket, newKey, endpoint.Bucket, key));
                                    if (result != null && result.HttpStatusCode == System.Net.HttpStatusCode.OK)
                                    {
                                        try
                                        {
                                            ossClient.DeleteObject(endpoint.Bucket, tempKey);
                                            ossClient.DeleteObject(endpoint.Bucket, newKey);
                                        }
                                        catch { }
                                        return true;
                                    }
                                }
                                catch
                                {
                                    result = ossClient.CopyObject(new Aliyun.OSS.CopyObjectRequest(endpoint.Bucket, tempKey, endpoint.Bucket, key));
                                }
                            }
                        }
                        catch
                        {
                            try
                            {
                                if (file.CanSeek)
                                {
                                    file.Seek(0, System.IO.SeekOrigin.Begin);
                                    return this.SaveFile(endpoint, key, file);
                                }
                            }
                            catch { }
                            return false;
                        }
                    }//end lock
                }
            }

            return defaultValue;
        }

        public System.IO.Stream GetFile(EndpointParameter endpoint, string key)
        {
            if (!string.IsNullOrEmpty(key))
            {
                lock (m_lock)
                {
                    var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);
                    var obj = ossClient.GetObject(endpoint.Bucket, key);
                    if (obj != null)
                    {
                        return obj.Content;
                    }
                }
            }

            return null;
        }

        public string GetURL(EndpointParameter endpoint, string key, int minutes = 30)
        {
            if (!string.IsNullOrEmpty(key))
            {
                var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);
                var obj = ossClient.GeneratePresignedUri(endpoint.Bucket, key, DateTime.Now.AddMinutes(minutes));
                if (obj != null)
                {
                    return obj.ToString();
                }
            }

            return null;
        }

        public string[] ListFiles(EndpointParameter endpoint, string prefix, int page, int pageSize, ref int total, List<string> allowFiles = null)
        {
            var ossClient = new Aliyun.OSS.OssClient(endpoint.Endpoint, endpoint.AccessKeyId, endpoint.AccessKeySecret);

            var list = ossClient.ListObjects(endpoint.Bucket, prefix);
            if (list != null)
            {
                IEnumerable<string> query = null;

                if (allowFiles != null)
                {
                    query = from o in list.ObjectSummaries
                            from t in allowFiles
                            where o.Key.Contains(t)
                            select o.Key;
                }
                else
                {
                    query = from o in list.ObjectSummaries
                            select o.Key;
                }

                total = query.Count();

                if ((page - 1) > 0)
                {
                    query = query.Skip((page - 1) * pageSize);
                    query = query.Take(pageSize);
                }
                else
                {
                    query = query.Take(pageSize);
                }

                return query.ToArray();
            }

            return null;
        }

    }

}
